#include "OclLapack.h"
#include <clAmdBlas.h>
#include "../AmdConvertEnum.h"
#include "../clUtils.h"
#include "../ClMem.h"
#include <cmath>
#include <memory>

using namespace std;

extern "C" {
    int lsame_(char *, char *);
}

void OclLapack::slarf(const char* side, int m, int n, 
		const cl_ptr v, int incV,
		float tau,
		cl_ptr c, int ldc,
		cl_ptr work) 
{
	Measure measure("slarf-ocl");

	/* Table of constant values */
	static float c_b4 = 1.f;
	static float c_b5 = 0.f;
	static int c__1 = 1;
	
	if (lsame_((char*)side, "L")) {
		// Form  H * C
		if (tau != 0.0f) {
			// w := C' * v
			sgemv("Transpose", m, n, 1, 
				c, ldc,
				v, incV, 
				0, 
				work, 1);
			// C := C - v * w'
			sger(m, n, -tau, v, incV, work, 1, c, ldc);
		}
    } else {
		// Form  C * H
		if (tau != 0) {
			// w := C * v
			sgemv("No transpose", m, n, 1, 
				c, ldc,
				v, incV, 
				0, work, 1);
			// C := C - w * v'			
			sger(m, n, -tau, work, 1, v, incV, c, ldc);
		}
    }
}

int OclLapack::slarf(char *side, int *m, int *n, float *v, 
	int *incv, float *tau, float *c, int *ldc, float *work)
{   
	size_t countV = (tolower(side[0]) == 'l') ? *m : *n;
	// XXX
	ClMem<float> memV;
	if (*tau != 0) {
		memV = ClMem<float>(queue, 1 + (countV - 1) * abs(*incv), v);
	}
			
	size_t sizeC = (*ldc) * (*n);
	ClMem<float> memC(queue, sizeC, c);
		
	size_t sizeWork = (tolower(side[0]) == 'l') ? *n: *m;
	ClMem<float> memWork(queue, sizeWork);	
	
	slarf(side, *m, *n,
		cl_ptr(memV), *incv,
		*tau,
		cl_ptr(memC), *ldc,
		cl_ptr(memWork));
	
	memC.beginRead(c, 0, sizeC).wait();
	
	return 0;
}
